/*jslint onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true,
         bitwise: true, regexp: true, newcap: true, immed: true, strict: true,
         white: true, indent: 2, maxlen: 80 */
/*global DOMException, JSON, encodeURIComponent, window */
(function () {
  "use strict";

  /**
   * Calculates the (top, left) absolute CSS position of the given element.
   */
  function locate(element) {
    if (element === element.ownerDocument.body) {
      return {
        top:  element.ownerDocument.body.offsetTop,
        left: element.ownerDocument.body.offsetLeft
      };
    }
    var box = element.getBoundingClientRect(),
        doc = element.ownerDocument,
        body = doc.body,
        docElem = doc.documentElement,
        clientTop = docElem.clientTop || body.clientTop || 0,
        clientLeft = docElem.clientLeft || body.clientLeft || 0;
    return {
      top: box.top +
           (window.pageYOffset || docElem.scrollTop || body.scrollTop) -
           clientTop,
      left: box.left +
            (window.pageXOffset || docElem.scrollLeft || body.scrollLeft) -
            clientLeft
    };
  }

  function makePopupRemover(popup) {
    return function () {
      if (popup.parentNode) {
        popup.parentNode.removeChild(popup);
      }
    };
  }

  if (!this.introducer) {
    // Eventually, the user-agent should have a built-in implementation of the
    // Introducer API with better security and UX. In the meantime, this file
    // provides a default implementation using an IFRAME on a globally trusted
    // site. Customers and Providers should not notice any change when this
    // default implementation is replaced by a native one.
    this.introducer = {};
    (function () {
      // Check that this user-agent supports all the stuff we need.
      if (!this.JSON || !this.postMessage || !this.localStorage) {
        this.introducer.register = function (registration, callback) {
          callback();
        };
        this.introducer.introduce = function (anchor, wanted, callback) {
          callback([]);
        };
        this.introducer.welcome = function (registrants, callback) {
        };
        return;
      }

      // This code runs in either a Customer or Provider page, so each can send
      // any request to the Introducer IFRAME and has full access to all
      // received data.  Consequently, the postMessage interface to an
      // Introducer IFRAME is designed to not reveal any information about
      // registrations and does not rely on the behavior of either the Customer
      // or the Provider.
      var introducerOrigin = 'https://webintroducer.net',
          introducerURL = introducerOrigin + '/',
          pseudoPorts = []; // MessagePorts implemented on Window postMessage

      // Implement MessagePort on top of IFRAME postMessage for legacy comm.
      function startPseudoPort(target) {
        var listeners = [],
            port = {
          addEventListener: function (type, listener) {
            if ('message' !== type) {
              return;
            }
            for (var i = 0; i < listeners.length; i += 1) {
              if (listeners[i] === listener) {
                return;
              }
            }
            listeners.push(listener);
          },
          removeEventListener: function (type, listener) {
            if ('message' !== type) {
              return;
            }
            for (var i = 0; i < listeners.length; i += 1) {
              if (listeners[i] === listener) {
                listeners.splice(i, 1);
                break;
              }
            }
          },
          dispatchEvent: function (msg) {
            if ('message' !== msg.type) {
              return;
            }
            if (port.onmessage) {
              port.onmessage(msg);
            }
            for (var i = 0; i !== listeners.length; i += 1) {
              listeners[i].apply(port, [ msg ]);
            }
            return true;
          },
          postMessage: function (message, ports) {
            if (ports && ports.length) {
              throw new DOMException(DOMException.INVALID_STATE_ERR);
            }
            target.postMessage(JSON.stringify(message), introducerOrigin);
          },
          close: function () {
            target = null;
            for (var i = 0; i < pseudoPorts.length; i += 1) {
              if (pseudoPorts[i].port === port) {
                if (pseudoPorts[i].onclose) {
                  pseudoPorts[i].onclose();
                }
                pseudoPorts.splice(i, 1);
                break;
              }
            }
          },
          start: function () {}
        };
        pseudoPorts.push({
          source: target,
          port: port
        });
        return port;
      }
      function onPseudoPortClose(port, action) {
        for (var i = 0; i < pseudoPorts.length; i += 1) {
          if (pseudoPorts[i].port === port) {
            pseudoPorts[i].onclose = action;
            break;
          }
        }
      }
      function listenForMessages(listener) {
        if (window.addEventListener) {
          window.addEventListener('message', listener, false);
        } else if (window.attachEvent) {
          window.attachEvent('onmessage', listener);
        }
      }
      listenForMessages(function (msg) {
        if (msg.origin !== introducerOrigin) {
          return;
        }
        for (var i = 0; i < pseudoPorts.length; i += 1) {
          if (pseudoPorts[i].source === msg.source) {
            pseudoPorts[i].port.dispatchEvent({
              type: 'message',
              ports: msg.ports,
              data: msg.data ? JSON.parse(msg.data) : undefined
            });
            break;
          }
        }
      });

      function onload(iframe, callback) {
        var once = function () {
          var tmp = callback;
          callback = undefined;
          if (tmp) {
            tmp();
          }
        };
        iframe.onload = once;

        // For compatibility with IE.
        iframe.onreadystatechange = function () {
          if ('complete' === iframe.readyState) {
            once();
          }
        };
      }

      // Enable clients to detect this is a simulated implementation.
      this.introducer.isSimulated = true;

      // Create or update a content Provider registration.
      this.introducer.register = function (registration, callback) {
        var doc = window.document,
            iframe = doc.createElement('iframe');
        iframe.src = introducerURL;
        iframe.scrolling = 'no';
        iframe.frameBorder = 0;
        iframe.style.borderWidth = 0;
        iframe.style.position = 'fixed';
        iframe.style.left = '0px';
        iframe.style.top = '0px';
        iframe.height = 40;
        iframe.width = '100%';
        doc.body.appendChild(iframe);
        onload(iframe, function () {
          var port = startPseudoPort(iframe.contentWindow);
          port.onmessage = function (msg) {
            port.onmessage = null;
            port.close();
            if (iframe.parentNode) {
              iframe.parentNode.removeChild(iframe);
            }
            if (null === msg.data[0]) {
              msg.data[0] = undefined;
            }
            callback.apply(null, msg.data);
          };
          port.postMessage({ name: 'register', argv: [ registration ] });
        });
      };

      // Ask to be introduced to a particular kind of Provider.
      this.introducer.introduce = function (anchor, wanted, callback) {
        if (!anchor) {
          anchor = window.document.body;
        }
        var iframe = anchor.ownerDocument.createElement('iframe'),
            offsets = locate(anchor);
        iframe.src = introducerURL;
        iframe.scrolling = 'no';
        iframe.frameBorder = 0;
        iframe.style.opacity = 0;
        iframe.style['-ms-filter'] =
          'progid:DXImageTransform.Microsoft.Alpha(opacity=0)';
        iframe.style.filter = 'alpha(opacity=0)';
        iframe.style.borderWidth = 0;
        iframe.style.position = 'absolute';
        iframe.style.top = offsets.top + 'px';
        iframe.style.left = offsets.left + 'px';
        iframe.height = anchor.offsetHeight + 1;
        iframe.width = anchor.offsetWidth;
        if (anchor === anchor.ownerDocument.body) {
          anchor.appendChild(iframe);
        } else {
          anchor.parentNode.appendChild(iframe);
        }
        onload(iframe, function () {
          var port = startPseudoPort(iframe.contentWindow);
          port.onmessage = function (msg) {
            port.onmessage = null;
            if (msg.data[2]) {
              iframe.removeAttribute('style');
              iframe.height = 0;
              iframe.width = 0;
              msg.data[2] = iframe;
              iframe = null;
            } else {
              msg.data[2] = undefined;
            }
            if (msg.data[1]) {
              if (msg.ports && msg.ports.length) {
                msg.data[1] = msg.ports[0];
              } else {
                if (iframe) {
                  // Need to keep the IFRAME to support messaging.
                  iframe.height = 0;
                  iframe.width = 0;
                  onPseudoPortClose(port, makePopupRemover(iframe));
                  iframe = null;
                }
                msg.data[1] = port;
                port = null;
              }
            } else {
              msg.data[1] = undefined;
            }
            if (port) {
              port.close();
              port = null;
            }
            if (iframe) {
              if (iframe.parentNode) {
                iframe.parentNode.removeChild(iframe);
              }
              iframe = null;
            }
            callback.apply(null, msg.data);
          };
          port.postMessage({ name: 'introduce', argv: [ wanted ] });
        });
      };

      // Inform the Introducer that this Provider page can be introduced by UX
      // determined by any of the specified registration origins.
      this.introducer.welcome = function (registrants, callback) {
        var source = window.parent === window ? window.opener : window.parent,
            port = startPseudoPort(source);
        port.onmessage = function (msg) {
          // The introduction happened via an allowed UX.
          port.onmessage = null;
          if (msg.data[0]) {
            if (msg.ports && msg.ports.length) {
              msg.data[0] = msg.ports[0];
            } else {
              msg.data[0] = port;
              port = null;
            }
          } else {
            msg.data[0] = undefined;
          }
          if (port) {
            port.close();
            port = null;
          }
          callback.apply(null, msg.data);
        };
        port.postMessage({ name: 'welcome', argv: [ registrants ] });
      };
    }());
  }

  // The rest of this file contains application specific APIs built on top of
  // the Introducer API. These application specific APIs are not expected to
  // ever be natively implemented by the user-agent.

  function iterate(list, predicate) {
    var i = 0, end = list.length, found;
    for (; i < end && undefined === found; i += 1) {
      found = predicate(list[i], i);
    }
    return found;
  }

  /**
   * Produces the JSONML representation of a DOM node.
   */
  function asJSONML(element) {
    var jml;
    switch (element.nodeType) {
    case 3:   // text node
    case 4:   // CDATA node
      jml = String(element.nodeValue);
      break;
    case 1:   // element
    case 9:   // document
    case 11:  // documentFragment
      jml = [ element.tagName, {} ];
      iterate(element.attributes, function (attribute) {
        if (attribute.specified) {
          switch (attribute.name) {
          case 'action':
          case 'cite':
          case 'data':
          case 'formaction':
          case 'href':
          case 'icon':
          case 'manifest':
          case 'poster':
          case 'src':
            // Get the corresponding absolute URL.
            jml[1][attribute.name] = element[attribute.name] || attribute.value;
            break;
          case 'style':
            jml[1].style = element.style.cssText || attribute.value;
            break;
          default:
            jml[1][attribute.name] = attribute.value;
          }
        }
      });
      iterate(element.childNodes, function (node) {
        var child = asJSONML(node);
        if (undefined !== child) {
          jml.push(child);
        }
      });
      break;
    }
    return jml;
  }

  /**
   * pending interactions that can be cancelled
   */
  var pending = [],
      useBookmarkDefault = false;

  /**
   * Fire a custom "bookmark" event so that Customer can react.
   */
  function bookmarked(anchor, data) {
    if (anchor.dispatchEvent) {
      var msg;
      try {
        msg = anchor.ownerDocument.createEvent('CustomEvent');
        msg.initCustomEvent('bookmark', true, false, data);
      } catch (e) {
        msg = anchor.ownerDocument.createEvent('HTMLEvents');
        msg.initEvent('bookmark', true, false);
      }
      anchor.dispatchEvent(msg);
    }
  }

  function bookmarkDefault(anchor) {
    var doc = anchor.ownerDocument,
        popup = doc.createElement('div'),
        offsets = locate(anchor),
        href = anchor.href,
        popular = [ {
      alt: 'Facebook',
      icon: '' +
            'AIAAAAAEABAAAAAAAgAAAABILAAASCwAAEAAAABAAAACYWTsAnmJFAKt4YACseWE' +
            'AtIRtAPTu6wD%2F%2F%2F8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAd3d3d3d3d3dzAAAAAAAAN3FERERGZEQXcUREREZkRBdwAAAABmAAB3AAA' +
            'AAGYAAHcAAAAAZgAAdwAAAFVmVQB3AAAAZmZmAHcAAAAAZgAAdwAAAABmAAB3AAA' +
            'AAFZmAHcAAAAAJWYAdwAAAAAAAAB3MAAAAAAAA3d3d3d3d3d3f%2F%2FwAAgAEAA' +
            'IABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAA' +
            'IABAAD%2F%2FwAA',
      name: 'Like it!',
      window: 'http://www.facebook.com/share.php?u='
    }, {
      alt: 'Twitter',
      icon: '' +
            'AIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD%2F%2F%2F8A%2F%2F%2F' +
            '%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%' +
            '2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%' +
            '2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%' +
            '2FwD%2F%2F%2F8A%2Fv7%2BD%2F7%2B%2Fj%2F%2B%2Fv5g%2Fv7%2BYP7%2B%2F' +
            'mD%2B%2Fv5I%2Fv7%2BKP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%' +
            '2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2B%2Fv4H%2Fv7%2BUPbv4pH' +
            'gx47B1K9Y3tWwWN7Ur1je3sKCx%2BrbuKj%2B%2Fv5n%2Fv7%2BGP%2F%2F%2FwD' +
            '%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2B%2Fv4Y%2BfbweM2ycMe2iB7%2' +
            'FvI0f%2F8STIf%2FKlyL%2FzJki%2F8yZIv%2FLmCL%2F0ahK5%2FHp1JH%2B%2F' +
            'v4Y%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A7OTTaquHN%2BCujkXPs5ZTv6N' +
            '6G%2F%2B2iB7%2FxpUh%2F8yZIv%2FMmSL%2FzJki%2F8yZIv%2FKmy738OjUi%2' +
            'F%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAMKtfY7w6%2BEf%2F%2F%2F%2FAP%' +
            '2F%2F%2FwD%2F%2F%2F8A3sqbp8iWIf%2FMmSL%2FzJki%2F8yZIv%2FMmSL%2Fy' +
            '5gi%2F8mePO7%2B%2Fv4w%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%' +
            '2F%2FAP%2F%2F%2FwD%2B%2Fv4H%2Fv7%2BV9CtWN3KmCL%2FzJki%2F8yZIv%2F' +
            'MmSL%2FzJki%2F8yZIv%2FJlyH%2F5tSqp%2F7%2B%2FmD%2B%2Fv4%2F%2F%2F%' +
            '2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2BPXvJtGyZdXNnS%2F3y5gi%2F8qYIv%2F' +
            'LmCL%2FzJki%2F8yZIv%2FMmSL%2Fy5gi%2F82iPO7LqVfe0byMmf%2F%2F%2FwD' +
            '%2F%2F%2F8A%2Fv7%2BD%2FDo1JHKmy73ypci%2F8KSIP%2B%2FjyD%2FxpQh%2F' +
            '8uYIv%2FMmSL%2FzJki%2F8qYIv%2B%2FjyD%2FrIEd%2F9nKqH7%2F%2F%2F8A%' +
            '2F%2F%2F%2FAPPu4TzAlSz3wZEg%2F7mLH%2F%2BsgR3%2FuZdGz7mLH%2F%2FJl' +
            'yH%2FzJki%2F8yZIv%2FGlSH%2Fto0r9eXbxD%2FVx6dg%2F%2F%2F%2FAP7%2B%' +
            '2Fh%2Fp38WhtIsq9al%2FHP%2BkfyjuybaKgf%2F%2F%2FwCzjzjlwJAg%2F8qYI' +
            'v%2FJlyH%2Fu4wf%2F8CkYrn%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwDj2sR' +
            'MnHUa%2F7meYa7Vx6dg%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A2MmnYK6DH' +
            'f%2B%2BjiD%2Fvo4g%2F62CHf%2Fk2sQ%2F%2F%2F%2F%2FAP%2F%2F%2FwD%2F%' +
            '2F%2F8A8OvhH%2Ff07w%2F%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F' +
            '%2F8A%2F%2F%2F%2FAP%2F%2F%2FwC%2Fp3Cfpnwc%2F66GKvPg1LZ8%2F%2F%2F' +
            '%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%' +
            '2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%' +
            '2F%2F8A%2F%2F%2F%2FANXHp2DJtoqByLWKgf%2F%2F%2FwD%2F%2F%2F8A%2F%2' +
            'F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2' +
            'F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD' +
            '%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F' +
            '%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F' +
            '%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%' +
            '2F%2F%2F%2FAP%2F%2F%2FwD%2F%2F%2F8A%2F%2F%2F%2FAP%2F%2F%2FwD%2F%' +
            '2F%2F8A%2F%2F8AAP%2F%2FAADgPwAAwA8AAIAHAAB4BwAA%2BAMAAPAAAADgAQA' +
            'A4AMAAMEDAADPhwAA%2F48AAP%2FnAAD%2F%2FwAA%2F%2F8AAA%3D%3D',
      name: 'Tweet it!',
      window: 'http://twitter.com/share?url='
    }, {
      alt: 'Google',
      icon: '' +
            'AIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7PT7%2F3zF6%2F9' +
            'Ptu%2F%2FRbHx%2F0227%2F%2BTzvb%2F9vv5%2F97h0f9JeBz%2FNHoA%2Fz98A' +
            'v9AfAD%2FPHsA%2F0F6AP8AAAAA%2Fvz7%2F1%2B33%2F8Mp%2Bz%2FFrHw%2FxW' +
            'y8f8bs%2FT%2FHqrx%2F3zE7v%2F%2F%2F%2F7%2Ft8qp%2FzF2A%2F87gwH%2FP' +
            '4ID%2Fz59AP8%2BegD%2FQ3kA%2F97s8v8botj%2FELn3%2Fwy58f8PtfL%2FD7L' +
            'w%2Fxuz9P8vq%2Bf%2F8%2Fn%2F%2F%2F779v9KhR3%2FOYYA%2F0GFAv88hgD%2' +
            'FQIAC%2Fz17AP%2F0%2B%2Fj%2FN6bM%2FwC07%2F8Cxf7%2FCsP7%2Fwm%2B9v8' +
            'Aqur%2FSrDb%2F%2F7%2B%2Fv%2F%2F%2FP7%2FVZEl%2FzSJAP87jQD%2FPYYA%' +
            '2F0OBBf8%2BfQH%2F%2F%2F3%2F%2F9Dp8%2F84sM7%2FCrDf%2FwC14%2F8CruL' +
            '%2FKqnW%2F9ns8f%2F8%2Fv%2F%2F4OjX%2Fz%2BGDf85kAD%2FPIwD%2Fz2JAv8' +
            '%2BhQD%2FPoEA%2F9C7pv%2F97uv%2F%2F%2F%2F%2B%2F9Xw%2Bv%2Bw3ej%2Fl' +
            's%2Fe%2F%2Brz9%2F%2F%2F%2F%2F%2F%2F%2B%2Fz6%2F22mSf8qjQH%2FOJMA%' +
            '2FzuQAP85iwL%2FPIgA%2FzyFAP%2BOSSL%2FnV44%2F7J%2BVv%2FAkG7%2F7tr' +
            'P%2F%2F7%2F%2Ff%2F9%2F%2F7%2F6%2FLr%2F2uoRv8tjQH%2FPJYA%2FzuTAP8' +
            '7kwD%2FPY8A%2Fz2KAP89hAD%2Folkn%2F6RVHP%2BeSgj%2FmEgR%2F%2FHo3%2' +
            'F%2F%2B%2Fv7%2F5Ozh%2F1GaJv8tlAD%2FOZcC%2FzuXAv84lAD%2FO5IC%2Fz2' +
            'PAf89iwL%2FOIkA%2F6hWFf%2BcTxD%2Fpm9C%2F76ihP%2F8%2Fv%2F%2F%2B%2' +
            'F%2F%2F%2F8nav%2F8fdwL%2FNZsA%2FzeZAP83mgD%2FPJQB%2FzyUAf84jwD%2' +
            'FPYsB%2Fz6HAf%2BfXif%2F1r6s%2F%2F79%2F%2F%2F58u%2F%2F3r%2Bg%2F%2' +
            'B3i2v%2F%2B%2F%2F3%2FmbiF%2FyyCAP87mgP%2FOpgD%2FzeWAP85lgD%2FOpE' +
            'B%2Fz%2BTAP9ChwH%2F7eHb%2F%2F%2F%2F%2Fv%2F28ej%2FtWwo%2F7tUAP%2B' +
            '5XQ7%2F5M%2B5%2F%2F%2F%2F%2Fv%2BbsZn%2FIHAd%2FzeVAP89lgP%2FO5MA%' +
            '2FzaJCf8tZTr%2FDyuK%2F%2F3%2F%2F%2F%2F9%2F%2F%2F%2F0qmC%2F7lTAP%' +
            '2FKZAT%2FvVgC%2F8iQWf%2F%2B%2F%2F3%2F%2F%2Fj%2F%2Fygpx%2F8GGcL%2' +
            'FESax%2FxEgtv8FEMz%2FAALh%2FwAB1f%2F%2F%2Ff7%2F%2F%2Fz%2F%2F758O' +
            '%2F%2FGXQL%2FyGYC%2F8RaAv%2FOjlf%2F%2B%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F9QU93%2FBAD0%2FwAB%2F%2F8DAP3%2FAAHz%2FwAA5f8DAtr%2F%2F%2F%2F%2' +
            'F%2F%2Fv7%2B%2F%2B2bCT%2FyGMA%2F89mAP%2FBWQD%2F0q%2BD%2F%2F%2F%2' +
            'B%2F%2F%2F%2F%2FP7%2FRkbg%2FwEA%2Bf8AA%2Fz%2FAQH5%2FwMA8P8AAev%2' +
            'FAADf%2F%2F%2F7%2FP%2F%2F%2F%2F7%2FuINQ%2F7lXAP%2FMYwL%2FvGIO%2F' +
            '%2FLm3P%2F8%2Fv%2F%2F1dT2%2FwoM5%2F8AAP3%2FAwH%2B%2FwAB%2Ff8AAfb' +
            '%2FBADs%2FwAC4P8AAAAA%2F%2Fz7%2F%2BLbzP%2BmXyD%2FoUwE%2F9Gshv%2F' +
            '8%2F%2F3%2F7%2FH5%2Fzo%2Fw%2F8AAdX%2FAgL6%2FwAA%2Ff8CAP3%2FAAH2%' +
            '2FwAA7v8AAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA%3D%3D',
      name: 'Buzz it!',
      window: 'http://www.google.com/buzz/post?url='
    }, {
      alt: 'Digg',
      icon: '' +
            'AIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAADezr1ImmYw55BXG%2F%2B' +
            'QVxv%2FkFcb%2F5BXG%2F%2BQVxv%2FkFcb%2F5BXG%2F%2BQVxv%2FkFcb%2F5B' +
            'XG%2F%2BQVxv%2FkFcb%2F5pmMOfezr1Im2gy5ZFYHf%2BRWR7%2FkVke%2F5FZH' +
            'v%2BRWR7%2FkVke%2F5FZHv%2BRWR7%2FkVke%2F5FZHv%2BRWR7%2FkVke%2F5F' +
            'ZHv%2BRWB3%2Fm2gy5ZBXG%2F%2BSWh%2F%2Fklof%2F5JaH%2F%2BSWh%2F%2Fk' +
            'lof%2F5JaH%2F%2BSWh%2F%2Fklof%2F5JaH%2F%2BSWh%2F%2Fklof%2F5JaH%2' +
            'F%2BSWh%2F%2Fklof%2F5BXG%2F%2BQVxv%2Fk1sg%2F5NbIP%2BTWyD%2Fk1sg%' +
            '2F5NbIP%2BTWyD%2Fk1sg%2F5NbIP%2BTWyD%2Fk1sg%2F5NbIP%2BTWyD%2Fk1s' +
            'g%2F5NbIP%2BQVxv%2FkFcb%2F5NcIv%2BTXCL%2Fk1wi%2F5NcIv%2BTXCL%2Fk' +
            '1wi%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F5NcIv%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2BTXCL%2FkFcb%2F5BXG' +
            '%2F%2BVXiX%2FlV4l%2F5VeJf%2BVXiX%2FlV4l%2F5VeJf%2BVXiX%2FlV4l%2F' +
            '%2F%2F%2F%2F%2F%2BVXiX%2FlV4l%2F5VeJf%2F%2F%2F%2F%2F%2FlV4l%2F5B' +
            'XG%2F%2BQVxv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Fl' +
            'mAn%2F%2F%2F%2F%2F%2F%2BWYCf%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2FlmAn%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F5ZgJ%2F%2BQVxv%2FkFcb%2F%2F%2F%2F%2F%2F%2BXYin%2F%2F%2F%2F' +
            '%2F%2F5diKf%2F%2F%2F%2F%2F%2Fl2Ip%2F%2F%2F%2F%2F%2F%2BXYin%2F%2F' +
            '%2F%2F%2F%2F5diKf%2F%2F%2F%2F%2F%2Fl2Ip%2F%2F%2F%2F%2F%2F%2BXYin' +
            '%2FkFcb%2F5BXG%2F%2F%2F%2F%2F%2F%2FmGMr%2F%2F%2F%2F%2F%2F%2BYYyv' +
            '%2F%2F%2F%2F%2F%2F5hjK%2F%2F%2F%2F%2F%2F%2FmGMr%2F%2F%2F%2F%2F%2' +
            'F%2BYYyv%2F%2F%2F%2F%2F%2F5hjK%2F%2F%2F%2F%2F%2F%2FmGMr%2F5BXG%2' +
            'F%2BQVxv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FmWQt%' +
            '2F%2F%2F%2F%2F%2F%2BZZC3%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2FmWQt%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F5lkLf%2BQVxv%2FkFcb%2F5pmMP%2BaZjD%2F%2F%2F%2F%2F%2F5pmMP%2BaZ' +
            'jD%2FmmYw%2F5pmMP%2BaZjD%2FmmYw%2F5pmMP%2BaZjD%2FmmYw%2F5pmMP%2B' +
            'aZjD%2FkFcb%2F5BXG%2F%2BbZzH%2Fm2cx%2F%2F%2F%2F%2F%2F%2BbZzH%2F%' +
            '2F%2F%2F%2F%2F5tnMf%2BbZzH%2Fm2cx%2F5tnMf%2BbZzH%2Fm2cx%2F5tnMf%' +
            '2BbZzH%2Fr4Va%2F5BXG%2F%2BQVxv%2FnGkz%2F5xpM%2F%2BcaTP%2FnGkz%2F' +
            '5xpM%2F%2BcaTP%2FnGkz%2F5xpM%2F%2BcaTP%2FnGkz%2F5xpM%2F%2BcaTP%2' +
            'FnGkz%2F5xpM%2F%2BQVxv%2FkFcb%2F5xpNP%2BcaTT%2FnGk0%2F5xpNP%2Bca' +
            'TT%2FnGk0%2F5xpNP%2BcaTT%2FnGk0%2F5xpNP%2BcaTT%2FnGk0%2F5xpNP%2B' +
            'caTT%2FkFcb%2F5pmMOeZZC3%2FnWs2%2F51rNv%2Bdazb%2FnWs2%2F51rNv%2B' +
            'dazb%2FnWs2%2F51rNv%2Bdazb%2FnWs2%2F51rNv%2Bdazb%2FmWQt%2F5pmMOf' +
            'j1cY%2Bp3pLyZBXG%2F%2BQVxv%2FkFcb%2F5BXG%2F%2BQVxv%2FkFcb%2F5BXG' +
            '%2F%2BQVxv%2FkFcb%2F5BXG%2F%2BQVxv%2FkFcb%2F6d6S8nj1cY%2BgAEAAAA' +
            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAgAEAAA%3D%3D',
      name: 'Digg it!',
      window: 'http://digg.com/submit?url='
    }, {
      alt: 'StumbleUpon',
      icon: '' +
            'AIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAA' +
            'NAAAAIAAAADoAAABXAAAAbwAAAHkAAAB5AAAAbQAAAFYAAAA5AAAAIAAAAA0AAAA' +
            'DAAAAAAAAAAEAAAANAAAAKQAAAFFjOQCdk1QA95JJAP%2BSSgD%2FcjgA6UAgAKc' +
            'AAACOAAAAdQAAAFAAAAApAAAADQAAAAAAAAAGAAAAH4dTAZSdWgD6nlYA%2F6JaA' +
            'P%2BjXAD%2Fo1sA%2F6JZAP%2BcUwD%2FiEUA9UolAKcAAACBAAAAUQAAACAAAAA' +
            'BAAAADp12H427cwH%2Ft24A%2F7ZuAP%2B4bgD%2FuG8A%2F7duAP%2B4bwD%2Fq' +
            'mIA%2F5tSAP%2BNSQD4SiUApwAAAHUAAAA5AAAABAAAABrCkSf1uYMX%2F7R%2FE' +
            'f%2BobgH%2Fm1QA%2F6plAP%2BlXgD%2FrWgA%2F8SHDf%2FDixf%2FoFwA%2F4J' +
            'BAPUAAACPAAAAVgAAAAbb29iJ%2Fv77%2F%2F7%2B%2FP%2F%2B%2Fvz%2F%2Fv3' +
            '4%2F%2B7amP%2BkWQH%2FpVkA%2F%2B3Qf%2F%2F%2B%2Ffb%2F%2Ff36%2F%2FP' +
            'pv%2F%2BybAP%2FSSUApwAAAG0AAAAIAZABiym%2BGv8nuxf%2FIrUU%2F3PcZv%' +
            '2F%2B%2Fv3%2FqHYQ%2F7J3CP%2F%2B%2FfX%2FjN2C%2F0rKPP%2F7%2Fvn%2F2' +
            'rdv%2F3xDAOkAAAB4AAAACAzFDP8BrAH%2FMcYl%2F4Thdv%2FM%2BMT%2F%2Fv7' +
            '6%2F614Ff%2B0gB%2F%2F%2Fv7%2B%2FzbELP8AswD%2F7%2F3q%2F%2BzSof%2B' +
            'YVAD%2FAAAAdwAAAAcLwgr%2FGLYP%2F%2Fj%2B9f%2F99%2BP%2F9uOv%2F9mxW' +
            'f%2BWUgD%2FrXsg%2F%2F7%2B%2Fv81wCj%2FAKwA%2F%2B796v%2FozqL%2FlVI' +
            'A%2FwAAAGsAAAAFB7gHwTXFLP%2F%2B%2Fv7%2F16xT%2F7NuCv%2BpZQX%2FqmY' +
            'G%2F8KbTv%2F%2B%2Fv7%2FJ7oa%2FwCsAP%2Fw%2Fer%2F582i%2F247AN4AAAB' +
            'TAAAAAgGgAYQFvQP%2FyvS%2F%2F%2F7%2B%2BP%2F9%2B%2Bz%2F%2Ffvs%2F%2' +
            'F387f%2F%2B%2Fvz%2F3PvP%2FwO3Av8BtAD%2F7%2F3q%2F%2BbNov9cLwCaAAA' +
            'AMwAAAAEs2Cc4G9kX9QLFAf8jwRP%2FLsYf%2FzHJIf8wySH%2FMswi%2FwjJA%2' +
            'F8AwQD%2FALwA%2F%2FD96%2F%2FDspTpAAAAPAAAABUAAAAAAAAAASvUJzki6yL' +
            '4C9oL%2FwXUBf8B0AH%2FANAA%2FwDRAP8AzwD%2FAM8A%2FwG7AP%2Fk8d74AAA' +
            'APQAAABcAAAAFAAAAAAAAAAAAAAABK9QnOTHxLPUZ6xn%2FDt8O%2FwnZCf8C1AL' +
            '%2FANEA%2FwDSAP8CyAD1AAAAMwAAABYAAAAGAAAAAQAAAAAAAAAEAAAAAAAAAAE' +
            's2Cc4EtgShCncI%2BcT6BP%2FDN8L%2Fw3UDcIKvQmKAAAAHAAAAA4AAAAEAAAAA' +
            'QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAGAAAACAAAAAkAAAAJAAAAB' +
            'wAAAAQAAAABAAAAAAAAAAAAAAAA%2F%2F8AAP5%2FAAD4HwAA4A8AAOAHAADAAwA' +
            'AwAMAAIABAACAAQAAwAMAAMADAADgBwAA8A8AAPgfAAD%2BfwAA%2F%2F8AAA%3D' +
            '%3D',
      name: 'Thumbs up!',
      window: 'http://www.stumbleupon.com/submit?url='
    }, {
      alt: 'Delicious',
      icon: '' +
            'AaAQAAI4DAAAoAAAAEAAAACAAAAABABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0tLT0tLT0tLT0tLT0tLT0tLT0tLT0tL' +
            'T%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'y%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy0HQy0HQy0HQy0HQy0HQy0HQy0HQ' +
            'yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAAAAAAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%' +
            '2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP' +
            '%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP%2FS0tP%2' +
            'F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2FwAAAP8AA' +
            'AD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2F0tLT%2F9LS0%2F%2FS0' +
            'tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F8AAAD%2FAAAA%2FwAAAP8' +
            'AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2' +
            'F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwA' +
            'AAP8AAAD%2FAAAA%2FwAAAP%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F' +
            '9LS0%2F%2FS0tP%2F0tLT%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2F' +
            'wAAAP8AAAD%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tL' +
            'T%2F9LS0%2F8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%' +
            '2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP' +
            '%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP8AAAD%2FAAAA%2FwAAAP%2FS0tP%2' +
            'F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F9LS0%2F%2FS0tP%2F0tLT%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy%2F' +
            '9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F9B0Mv%2FQdDL%2' +
            'F0HQy%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2FQdDL%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FQdDL%2F0HQy%2F9B0M' +
            'v%2FQdDL%2F0HQy%2F9B0Mv%2FQdDL%2F0HQy%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F0HQy%2F9B0Mv%2FQdDL%2F0' +
            'HQy%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2F' +
            'QdDL%2F0HQy%2F9B0Mv%2FQdDL%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FQdDL%2F0HQy%2F9B0Mv%2FQdDL%2F0HQy%' +
            '2F9B0Mv%2FQdDL%2F0HQy%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%' +
            '2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F0HQy%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2FQd' +
            'DL%2F0HQy%2F9B0Mv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2' +
            'F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F' +
            '%2F%2F%2F%2F%2F%2F9B0Mv%2FQdDL%2F0HQy%2F9B0Mv%2FQdDL%2F0HQy%2F9B' +
            '0Mv%2FQdDL%2FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D',
      name: 'Tag it!',
      window: 'http://www.delicious.com/post?url='
    } ];

    // List the popular defaults.
    iterate(popular, function (provider) {
      var option = doc.createElement('a');
      option.style.display = 'block';
      option.style.height = '16px';
      option.style.padding = '2px 0px 2px 20px';
      option.style.backgroundImage = 'url("' + provider.icon + '")';
      option.style.backgroundRepeat = 'no-repeat';
      option.style.font = 'menu';
      option.appendChild(doc.createTextNode(provider.name));
      option.setAttribute('title', provider.alt +
          (provider.description ? ': ' + provider.description : ''));
      option.setAttribute('href', provider.window + encodeURIComponent(href));
      option.setAttribute('target', '_blank');
      option.onfocus = function () {
        option.style.backgroundColor = '#ffa';
      };
      option.onblur = function () {
        option.style.backgroundColor = 'transparent';
      };
      option.onmouseover = function () {
        option.focus();
      };
      option.onkeydown = function (e) {
        e = e || window.event;
        if (40 === e.keyCode) {
          if (option.nextSibling) {
            option.nextSibling.focus();
          }
          e.returnValue = false;
          if (e.preventDefault) {
            e.preventDefault();
          }
        } else if (38 === e.keyCode) {
          if (option.previousSibling) {
            option.previousSibling.focus();
          }
          e.returnValue = false;
          if (e.preventDefault) {
            e.preventDefault();
          }
        } else if (27 === e.keyCode) {
          popup.parentNode.removeChild(popup);
        }
      };
      option.onclick = function () {
        bookmarked(anchor, null);
      };
      popup.appendChild(option);
    });

    popup.style.backgroundColor = 'white';
    popup.style.color = 'black';
    popup.style.border = 'thin outset black';
    popup.style.position = 'absolute';
    popup.style.top = (offsets.top + anchor.offsetHeight) + 'px';
    popup.style.left = offsets.left + 'px';
    if (anchor === doc.body) {
      anchor.appendChild(popup);
    } else {
      anchor.parentNode.appendChild(popup);
    }
    popup.firstChild.focus();
    pending.push(makePopupRemover(popup));
  }

  /**
   * A social bookmarking API.
   */
  function bookmark(anchor, later) {
    useBookmarkDefault = false;
    var wanted = [ 'http://web-send.org/bookmark/' ],
        mimeParser = /^([\w!#\$%&'*+-\.\^`|~]*)\/([\w!#\$%&'*+-\.\^`|~]*)(;|$)/,
        mimeType = mimeParser.exec(anchor.getAttribute('type') || '');
    if (mimeType) {
      wanted.push(wanted[0] + '#' + mimeType[1].toLowerCase() + '/');
      wanted.push(wanted[1] + mimeType[2].toLowerCase());
    }
    window.introducer.introduce(anchor, wanted,
                                function (agreed, provider, dialog) {
      if (!agreed) {
        // User cancelled request.
        return;
      }
      if (!provider) {
        // No matching Provider.
        useBookmarkDefault = true;
        if (!later) {
          bookmarkDefault(anchor);
        }
        return;
      }

      if (dialog) {
        // Restrict the presentation space given to the selected Provider.
        var offsets = locate(anchor);
        dialog.scrolling = 'no';
        dialog.frameBorder = 0;
        dialog.style.borderWidth = 0;
        dialog.style.position = 'absolute';
        dialog.style.zIndex = 1;
        dialog.style.top = (offsets.top + anchor.offsetHeight) + 'px';
        dialog.style.left = offsets.left + 'px';
        dialog.height = 100;
        dialog.width = 500;
      }

      // Send a description of the link element to the selected Provider.
      provider.postMessage([ asJSONML(anchor) ]);

      // Clean-up after done.
      function cleanup() {
        provider.close();
        if (dialog && dialog.parentNode) {
          dialog.parentNode.removeChild(dialog);
        }
      }
      provider.onmessage = function (msg) {
        cleanup();
        bookmarked(anchor, msg.data);
      };
      pending.push(cleanup);
    });
  }

  function initiateIntroduction(e) {
    e = e || window.event;

    // On deliberate user input, dismiss any pending interactions.
    if ('click' === e.type) {
      while (pending.length) {
        pending.pop()();
      }
    }

    // Determine if user action triggers a new introduction.
    var target = e.target || e.srcElement;
    while ('A' !== target.tagName) {
      target = target.parentNode;
      if (!target) {
        return;
      }
    }
    if (!target.rel) {
      return;
    }
    return iterate(target.rel.split(' '), function (rel) {
      if (/^bookmark$/i.test(rel)) {
        if ('click' === e.type) {
          if (1 === (e.button || 1) &&
              !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
            e.returnValue = false;
            if (e.preventDefault) {
              e.preventDefault();
            }
            bookmark(target);
          }
        } else {
          if (!useBookmarkDefault) {
            bookmark(target, true);
          }
        }
        return true;
      }
    });
  }
  if (window.addEventListener) {
    window.addEventListener('click', initiateIntroduction, false);
  } else if (window.document.attachEvent) {
    window.document.attachEvent('onclick', initiateIntroduction);
  }
  if (window.introducer.isSimulated) {

    // Prepare an introduction click target in a preceeding mouseover event.
    if (window.addEventListener) {
      window.addEventListener('mouseover', initiateIntroduction, false);
    } else if (window.document.attachEvent) {
      window.document.attachEvent('onmouseover', initiateIntroduction);
    }
  }
}());
